﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Media;

namespace Invini.Training
{
    public enum VisualChildIndexDirection
    {
        FromBeggining,
        FromEnd
    }

    public class VisualChildComponent : IPathComponent
    {
        public string Type
        {
            get;
            set;
        }
        public string Key
        {
            get;
            set;
        }
        public uint? Index
        {
            get;
            set;
        }
        public VisualChildIndexDirection IndexDirection
        {
            get;
            set;
        }

        public bool IncludeMe
        {
            get;
            set;
        }

        public IEnumerable<object> FindElements(object parentElement)
        {
            if (parentElement == null)
                return null;

            DependencyObject dpParentElement = parentElement as DependencyObject;
            if (dpParentElement == null)
                return null;

            IEnumerable<object> children = this.findChildren(dpParentElement, this.IncludeMe);
            if (children == null)
                return null;

            if (this.Index == null)
                return children;

            if (children.Count() <= this.Index)
                return null;

            if(this.IndexDirection == VisualChildIndexDirection.FromBeggining)
                return new object[] { children.ToArray()[(uint)this.Index] };

            return new object[] { children.ToArray()[(uint)(children.Count() - this.Index - 1)] };
        }

        private IEnumerable<object> findChildren(DependencyObject parent, bool includeParent = false)
        {
            if (parent == null || TrainingOptions.GetIgnore(parent))
                return null;

            if (includeParent
                && (String.IsNullOrWhiteSpace(this.Type) || parent.GetType().FullName == this.Type)
                && (String.IsNullOrWhiteSpace(this.Key) || TrainingOptions.GetKey(parent) == this.Key))
                return new object[] { parent };

            if (parent is Popup)
            {
                Popup popup = parent as Popup;
                if (popup.Child == null)
                    return null;

                if ((String.IsNullOrWhiteSpace(this.Type) || popup.Child.GetType().FullName == this.Type)
                    && (String.IsNullOrWhiteSpace(this.Key) || TrainingOptions.GetKey(popup.Child) == this.Key))
                    return new object[] { popup.Child };

                return this.findChildren(popup.Child);
            }

            List<object> children = new List<object>();
            int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < childrenCount; i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(parent, i);
                if ((String.IsNullOrWhiteSpace(this.Type) || child.GetType().FullName == this.Type)
                    && (String.IsNullOrWhiteSpace(this.Key) || TrainingOptions.GetKey(child) == this.Key))
                {
                    children.Add(child);
                    continue;
                }

                IEnumerable<object> nextChildren = this.findChildren(child);
                if(nextChildren != null)
                    children.AddRange(nextChildren);
            }

            return children;
        }
    }
}
